/***************************Copyright QYKJ   2019-08-20*************************
文  件：	topic.c
说  明：	消息订阅发布功能实现函数
编  写：	Unarty
修  改：	2019.08.20 创建 
*******************************************************************************/
#include "Topic.h"
#include "list.h"

typedef struct 
{
    u8_t topic;
    ListHandler_t push; //推送目标
}Topic_t; // 主题订阅表

ListHandler_t s_topic; 

static u8_t topicFind(void *src, void *dest);
static u8_t topicPush(void *listPaycoad, void *chagePoint);
static u8_t pushFind(void *src, void *dest);

/*******************************************************************************
  * @brief  初始化 
  * @note   None
  * @param  None
  * @retval None
*******************************************************************************/
void Topic_init(void){
    list_init(&s_topic);
}

/*******************************************************************************
  * @brief  发布主题
  * @note   None
  * @param  topic: 主题类型
  *         msg: 目标消息
  * @retval 发布结果，0：正常，-1 
*******************************************************************************/
void Pushlisher(Topic_e topic, void *msg){
    Topic_t *pT = list_find(&s_topic, topicFind, &topic);

    if (pT != null) {
        list_trans(&pT->push, topicPush, msg);//推送消息

        if (pT->push.count <= 0) {//没有主题订阅者了
            list_nodeDelete(&s_topic, pT);
        }
    }
}

/*******************************************************************************
  * @brief  订阅主题
  * @note   None
  * @param  topic: 主题类型
  *         push: 推送目标
  * @retval 订阅结果，0：订阅成功，-1 订阅主题添加失败，-2 订阅节点添加失败
*******************************************************************************/
int Subscriber(Topic_e topic, pushFun subscribers){
    pushFun *push;
    Topic_t *pT = list_find(&s_topic, topicFind, &topic);

    if (pT == null) { //没有相关主题订阅
        pT = list_nodeApply(sizeof(Topic_t));

        if (pT == null){
            return -1;
        }
        pT->topic = topic;
        list_init(&pT->push);
        list_bottomInsert(&s_topic, pT);
    }

    push = list_find(&pT->push, pushFind, (void*)&subscribers); //是否已存在订阅

    if (push == null) { //添加订阅
        push = list_nodeApply(sizeof(pushFun));

        if (push == null){
            return -2;
        }
        *push = subscribers;
        list_bottomInsert(&pT->push, push);
    }

    return 0;
}

/*******************************************************************************
  * @brief  主题查找
  * @note   None
  * @param  
  * @retval 
*******************************************************************************/
static u8_t topicFind(void *src, void *dest){
    Topic_t *pSrc = (Topic_t*)src;
    Topic_e *pDest = (Topic_e*)dest;

    if (pSrc->topic == *pDest) {
        return 0;
    }

    return -1;
}

/*******************************************************************************
  * @brief  主题消息推送
  * @note   None
  * @param  
  * @retval 
*******************************************************************************/
static u8_t topicPush(void *listPayload, void *chagePoint){
    pushFun push = *(pushFun*)listPayload;

    if (push(chagePoint) != 0) {
        return 0xFF; //删除订阅
    }

    return 1;
}

/*******************************************************************************
  * @brief  推送查找
  * @note   None
  * @param  
  * @retval 
*******************************************************************************/
static u8_t pushFind(void *src, void *dest){
    if (*(pushFun*)src == *(pushFun*)dest) {
        return 0;
    }

    return -1;
}

/*******************************Copyright QYKJ*********************************/
